﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;

namespace Ecobee.Net
{
	public abstract class ApiObjectCollection<T> : ObservableCollection<T>, IApiObjectCollection, IApiObjectCollection<T> where T : IApiObject, new()
	{
		public event EventHandler<ApiObjectCollectionChangedEventArgs> ApiObjectCollectionChanged = null;
		private string _propertyName = string.Empty;

		public ApiObjectCollection(string propertyName)
		{
			this.PropertyName = propertyName;
			this.CollectionChanged += ApiObjectCollection_CollectionChanged;
		}

		public string PropertyName
		{
			get
			{
				return _propertyName;
			}
			set
			{
				_propertyName = value;
			}
		}

		public virtual void Load(dynamic dataObject)
		{
			this.OnLoad(dataObject);
		}

		public bool ItemExists(dynamic dataObject)
		{
			return this.OnItemExists(dataObject);
		}

		public T GetItem(dynamic dataObject)
		{
			return this.OnGetItem(dataObject);
		}

		protected virtual void OnLoad(dynamic dataObject)
		{
			if (dataObject !=null && ((Newtonsoft.Json.Linq.JContainer)dataObject).Count > 0)
			{
				foreach (var item in dataObject)
				{
					T itemObject = default(T);

					if (this.ItemExists(item))
					{
						itemObject = this.GetItem(item);

						// ***
						// *** Load the item data
						// ***
						itemObject.FromDataObject(item);
					}
					else
					{
						itemObject = new T();
						
						// ***
						// *** Load the item data
						// ***
						itemObject.FromDataObject(item);

						this.Add(itemObject);

						itemObject.PropertyChanged += itemObject_PropertyChanged;
					}					
				}
			}
			else
			{
				this.Clear();
			}
		}

		private void itemObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			this.OnCollectionChanged(new ApiObjectCollectionChangedEventArgs(this.PropertyName, NotifyCollectionChangedAction.Replace));
		}

		protected bool OnItemExists(dynamic dataObject)
		{
			bool returnValue = false;

			var qry = from tbl in this
					  where tbl.UniqueKey == tbl.GetKeyValue(dataObject)
					  select tbl;

			returnValue = (qry.Count() == 1);

			return returnValue;
		}

		protected T OnGetItem(dynamic dataObject)
		{
			T returnValue = default(T);

			var qry = from tbl in this
					  where tbl.UniqueKey == tbl.GetKeyValue(dataObject)
					  select tbl;

			if (qry.Count() == 1)
			{
				returnValue = qry.Single();
			}

			return returnValue;
		}

		protected void OnCollectionChanged(ApiObjectCollectionChangedEventArgs e)
		{
			if (this.ApiObjectCollectionChanged != null)
			{
				this.ApiObjectCollectionChanged(this, e);
			}
		}

		private void ApiObjectCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			this.OnCollectionChanged(new ApiObjectCollectionChangedEventArgs(this.PropertyName, e.Action));
		}
	}
}
